package com.smh.demo1.a17;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.Collections;
import java.util.List;

/**
 * @author shiminghui
 * @date 2025/4/21 21:51
 * @description: TODO
 */
//@Configuration
@ComponentScan
@PropertySource("classpath:/application.yml") // 加载配置文件
@EnableConfigurationProperties({ServerProperties.class, WebMvcProperties.class}) // 启用配置属性的绑定
public class WebConfig {

    private static final Logger log = LoggerFactory.getLogger(WebConfig.class);

    // 这里这个两个类不生效,因为,这里不是使用springApplication容器启动的,他并不会读取配置文件
    //ServerProperties这些类就是通过ConfigurationProperties注解绑定配置文件的属性,这里注入,可以实现配置文件的更新,不需要修改代码

    // 内嵌的tomcat容器
    @Bean
    public TomcatServletWebServerFactory tomcatServletWebServerFactory(ServerProperties serverProperties, YamlPropertiesFactoryBean yamlPropertiesFactoryBean) {
        /*if (serverProperties == null){
            System.out.println("serverProperties is null");
            return null;
        }
        if (serverProperties.getPort() == null){
            System.out.println(serverProperties);
            System.out.println("serverProperties.getPort() is null");
        }*/
        int o = (int) yamlPropertiesFactoryBean.getObject().get("server.port");
        TomcatServletWebServerFactory servletWebServerFactory = new TomcatServletWebServerFactory();
        servletWebServerFactory.setPort(o);
        return servletWebServerFactory;
    }

    // 前端控制器
    @Bean
    public DispatcherServlet dispatcherServlet() {
        return new DispatcherServlet();
    }

    // 注册DispatcherServlet
    @Bean
    public DispatcherServletRegistrationBean dispatcherServletRegistrationBean(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, YamlPropertiesFactoryBean yamlPropertiesFactoryBean) {
        int o = (int) yamlPropertiesFactoryBean.getObject().get("spring.mvc.servlet.load-on-startup");
        DispatcherServletRegistrationBean registrationBean = new DispatcherServletRegistrationBean(dispatcherServlet, "/"); // 设置DispatcherServlet的映射路径
        registrationBean.setLoadOnStartup(o); // 设置启动顺序,越小优先级越高(设置这个属性后(大于0),DispatcherServlet会立刻初始化)
        return registrationBean;
    }

    // yaml配置文件解析器
    @Bean
    public YamlPropertiesFactoryBean yamlPropertiesFactoryBean() {
        YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
        yamlPropertiesFactoryBean.setResources(new ClassPathResource("application.yml"));
        return yamlPropertiesFactoryBean;
    }

    // DispatcherServlet 默认的初始化组件并不会创建为bean对象,这给我们的测试带来了困难,这里手动创建一个,并注册到spring容器中
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        log.info("自定义MappingHandler加载成功");
        return new RequestMappingHandlerMapping();
    }

    @Bean
    public MyRequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        log.info("自定义Adapter加载成功");
        MyRequestMappingHandlerAdapter handlerAdapter = new MyRequestMappingHandlerAdapter();
        List<HandlerMethodArgumentResolver> argumentResolvers =
                handlerAdapter.getCustomArgumentResolvers();
        // 添加一个自定义参数解析器
        if (argumentResolvers == null) {
            handlerAdapter.setCustomArgumentResolvers(Collections.singletonList(new TokenArgumentResolver()));
        } else {
            argumentResolvers.add(new TokenArgumentResolver());
        }
        // 添加一个自定义返回值解析器
        List<HandlerMethodReturnValueHandler> returnValueHandlers = handlerAdapter.getCustomReturnValueHandlers();
        if (returnValueHandlers == null) {
            handlerAdapter.setCustomReturnValueHandlers(Collections.singletonList(new YmlReturnValueHandler()));
        } else {
            returnValueHandlers.add(new YmlReturnValueHandler());
        }

        return handlerAdapter;
    }
}
